// SPDX-FileCopyrightText: 2023-2025 Sangfor Technologies Inc.
// SPDX-License-Identifier: Mulan PSL v2
package com.geniusai.aip.auth.utils;

/**
 * @author lingchuanzhou19320
 * @date 2022/6/9
 */
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * http 工具类
 */
@Slf4j
public abstract class HttpUtil {

    /**
     * 发送 http 请求
     */
    public static String request(HttpRequestBase httpRequest) {
        return request(httpRequest, 5000, 60000, false, null);
    }

    /**
     * 发送 http 请求
     */
    public static String request(HttpRequestBase httpRequest, int connectTimeout, int socketTimeout) {
        return request(httpRequest, connectTimeout, socketTimeout, false, null);
    }

    /**
     * 发送 http 请求. 不校验 ssl 证书, 慎用, 一般用在开发测试环境
     */
    public static String requestIgnoreSsl(HttpRequestBase httpRequest, Proxy proxy) {
        return request(httpRequest, 5000, 60000, true, proxy);
    }

    /**
     * 发送 http 请求
     */
    public static String request(HttpRequestBase httpRequest, int connectTimeout, int socketTimeout, boolean ignoreSsl, Proxy proxy) {
        HttpClientBuilder builder = HttpClients.custom();
        if (ignoreSsl) {
            try {
                SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                        return true;
                    }
                }).build();
                builder.setSSLSocketFactory(new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE));
            } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
                throw new RuntimeException(e);
            }
        }
        if (proxy != null) {
            HttpHost proxyHost = new HttpHost(proxy.getHost(), proxy.getPort());
            builder.setProxy(proxyHost);

            if (StringUtils.isNotEmpty(proxy.getUsername())) {
                CredentialsProvider credsProvider = new BasicCredentialsProvider();
                credsProvider.setCredentials(new AuthScope(proxy.getHost(), proxy.getPort()),
                        new UsernamePasswordCredentials(proxy.getUsername(), proxy.getPassword()));
                builder.setDefaultCredentialsProvider(credsProvider);
            }
        }
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build();

        try (CloseableHttpClient httpclient = builder.setDefaultRequestConfig(requestConfig).build()) {
            CloseableHttpResponse resp = httpclient.execute(httpRequest);
            if (resp.getStatusLine().getStatusCode() != 200) {
                log.warn("http request failed. request: {}, status: {}", httpRequest, resp.getStatusLine());
            }
            return EntityUtils.toString(resp.getEntity());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 不校验 ssl 证书
     */
    public static HttpClientBuilder createIngoreSslBuilder() {
        HttpClientBuilder builder = HttpClients.custom();
        try {
            SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                    return true;
                }
            }).build();
            builder.setSSLSocketFactory(new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE));
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            throw new RuntimeException(e);
        }

        return builder;
    }

    @Getter
    @Setter
    @AllArgsConstructor
    public static class Proxy {
        private String host;
        private int port;
        private String username;
        private String password;
    }
}
